package com.shaoyu.spring.study.validate.util;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @Desc :
 * @Author: shaoyu
 * @Date : 2022/9/13 18:21
 */
public class StringSimilarityUtil {


    public static double sim(String source,String target){
        return new CosineSimilarity(source,target).sim();
    }


    public static void main(String[] args) {
        System.out.println(StringSimilarityUtil.sim("123", "321"));
    }


    private static class CosineSimilarity {
        //Key=每一个字符 value[0]表示第一个字符串中字符的个数 value[1]表示第二个字符串中字符的个数
        Map<Character, int[]> vectorMap = new HashMap<>();

        private CosineSimilarity(String string1, String string2) {
            for (Character character1 : string1.toCharArray()) {
                if (vectorMap.containsKey(character1)) {
                    vectorMap.get(character1)[0]++;
                } else {
                    int[]tempArray = {1,0};
                    vectorMap.put(character1, tempArray);
                }
            }
            for (Character character2 : string2.toCharArray()) {
                if (vectorMap.containsKey(character2)) {
                    vectorMap.get(character2)[1]++;
                } else {
                    int[]tempArray = {0,1};
                    vectorMap.put(character2, tempArray);
                }
            }
        }
        // 求余弦相似度
        public double sim() {
            double result = 0;
            result = pointMulti(vectorMap) / sqrtMulti(vectorMap);
            return result;
        }
        private double sqrtMulti(Map<Character, int[]> paramMap) {
            double result = 0;
            result = squares(paramMap);
            result = Math.sqrt(result);
            return result;
        }
        // 求平方和
        private double squares(Map<Character, int[]> paramMap) {
            double result1 = 0;
            double result2 = 0;
            Set<Character> keySet = paramMap.keySet();
            for (Character character : keySet) {
                int[] temp = paramMap.get(character);
                result1 += (temp[0] * temp[0]);
                result2 += (temp[1] * temp[1]);
            }
            return result1 * result2;
        }
        // 点乘法
        private double pointMulti(Map<Character, int[]> paramMap) {
            double result = 0;
            Set<Character> keySet = paramMap.keySet();
            for (Character character : keySet) {
                int[] temp = paramMap.get(character);
                result += (temp[0] * temp[1]);
            }
            return result;
        }
    }
}
